

//我们现在的程序，不支持绑定多个ip,不能测试并发情况，所以需要改造一般，
//改造之后，就是我们大名鼎鼎的反应堆了

//epoll io
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>


#define MAX_EPOLL_EVENTS	1024





//因为是需要多个设备连接，所以需要一个保存fd的结体
struct ntyevent {
	int fd;
	
	int status;		//状态

	int (*callback)();
	void *arg;

	int event;

	long last_active;
};


//反应堆结构体
struct ntyreactor
{
	int epfd;
	struct ntyevent *event;
}


int nty_set_event(int sockfd, callback *callback, void *arg, struct ntyevent *ntyevent)
{
	ntyevent->fd = sockfd;
	ntyevent->callback = callback;
	ntyevent->last_active = time(NULL);
	ntyevent->arg = arg;
	
	return 0;
}



int nty_event_add(struct ntyreactor *reactor, int sockfd, int event, struct ntyevent *ntyevent)
{
	struct epoll_event event = {0};
	event.data.fd = sockfd;
	event.events = event;

	ntyevent->event = event;
	
	epoll_ctl(reactor->epfd, EPOLL_CTL_ADD, sockfd, &event);
	

	return 0;
}


int nty_event_del(struct ntyreactor *reactor, int event, struct ntyreactor *reactor)
{

	epoll_ctl(reactor->epfd, EPOLL_CTL_DEL, sockfd, NULL);

	return 0;
}



int ntyreactor_init(struct ntyreactor *reactor)
{
	if(reactor == NULL)  {
		printf("ntyreactor_init param is null\n");
		return -1;
	}

	reactor->epfd = epoll_create(1);
	if(reactor->epfd < 0)  {
		printf("epoll_create error\n");
		return -2;
	}

	reactor->event = (struct ntyevent *)malloc( MAX_EPOLL_EVENTS*sizeof(struct ntyevent) );
	if(reactor->event == NULL)  {
		printf("reactor->event malloc error\n");
		return -3;
	}


	return 0;
}


int ntyreactor_destory(struct ntyreactor *reactor)
{
	if(reactor == NULL)  {
		printf("ntyreactor_init param is null\n");
		return -1;
	}

	close(reactor->epfd);
	free(reactor->event);

	return 0;
}

int ntyreactor_addlistener(struct ntyreactor *reactor, int sockfd, int events, callback *callback)
{
	struct ntyevent ntyevent;

	nty_set_event(sockfd, callback, NULL, &ntyevent);
	nty_event_add(reactor, event, &ntyevent);


	return 0;
}


int my_listen(int port)
{
	int fd = -1;
	int ret = -1;

	fd = socket(AF_INET, SOCK_STREAM, 0);
	if(fd < 0)  {
		printf("fd error\n");
		return -1;
	}


	struct sockaddr_in server_addr = {0};
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(port);
	server_addr.sin_addr.s_addr = htonl(INADDR_ANY);	

	ret = bind(fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
	if(ret < 0) {
		printf("bind error\n");
		return -1;
	}

	ret = listen(fd, 5);
	if(ret < 0)  {
		printf("listen error\n");
		return -2;
	}

	return fd;
}



char buff[1024] = {0};


int main(int argc, char **argv)
{
	int i = 0;

	if(argc != 2) {
		printf("error\n");
		return -1;
	}


	//初始化
	struct ntyreactor reactor = {0};
	ntyreactor_init(&reactor);

	
	for(i=0; i<100; i++)  {
		int sockfd = my_listen(port+i);
		fcntl(sockfd, F_SETFL, O_NONBLOCK);

		

	}





	int port = atoi(argv[1]);
	
	int rsize = 0;


	struct epoll_event event = {0};
	struct epoll_event client_event[100] = {0};

	printf("port %d\n", port);

	

		
	



	while(1) {

		
		int nread = epoll_wait(epfd, client_event, 100, 0);
		if (nread < 0) {
			continue;
		}

		for(i=0; i<nread; i++)  {
			memset(&event, 0, sizeof(event));
			if(client_event[i].data.fd == sockfd) {
				//epoll_ctl(epfd, EPOLL_DEL, client_event[i].data.fd, NULL);

				struct sockaddr client_addr  = {0};
				socklen_t len = 0;
	
				int client_fd = accept(sockfd, &client_addr, &len);

				
				event.data.fd = client_fd;
				event.events = EPOLLIN;
				epoll_ctl(epfd, EPOLL_CTL_ADD, client_fd, &event);
				
			} else {
				epoll_ctl(epfd, EPOLL_CTL_DEL, client_event[i].data.fd, NULL);
				if(client_event[i].events == EPOLLIN) {
					

					rsize = recv(client_event[i].data.fd, buff,  sizeof(buff), 0);
					if(rsize <= 0)
						continue;
				
					printf("recv %s\n", buff);
					event.data.fd = client_event[i].data.fd;
					event.events = EPOLLOUT;
					epoll_ctl(epfd, EPOLL_CTL_ADD, client_event[i].data.fd, &event);
				} else if(client_event[i].events == EPOLLOUT) {
					send(client_event[i].data.fd,  buff, sizeof(buff), 0);
					printf("send %s\n", buff);
					memset(&buff, 0, sizeof(buff));
					event.data.fd = client_event[i].data.fd;
					event.events = EPOLLIN;
					epoll_ctl(epfd, EPOLL_CTL_ADD, client_event[i].data.fd, &event);
				}


			}

		}


	}


	return 0;
}




















